package mirrormonkey.state.module;

import java.util.Collection;

import mirrormonkey.core.module.CoreModule;
import mirrormonkey.framework.ConnectionInfo;
import mirrormonkey.framework.EntityProvider;
import mirrormonkey.framework.entity.EntityData;
import mirrormonkey.framework.entity.StaticEntityData;
import mirrormonkey.framework.member.DynamicMemberData;
import mirrormonkey.state.StateUpdateListener;
import mirrormonkey.state.member.inbound.InboundDynamicMemberStateData;
import mirrormonkey.state.member.inbound.InboundStaticMemberStateData;
import mirrormonkey.state.member.outbound.OutboundDynamicMemberStateData;
import mirrormonkey.state.member.outbound.OutboundStaticMemberStateData;
import mirrormonkey.state.messages.StateUpdateMessage;

import com.jme3.network.Message;
import com.jme3.network.MessageConnection;
import com.jme3.network.MessageListener;

public class StateUpdateMessageListener implements
		MessageListener<MessageConnection> {

	public final CoreModule coreModule;

	public final StateUpdateModule module;

	public final EntityProvider entityProvider;

	public StateUpdateMessageListener(StateUpdateModule module) {
		coreModule = module.appState.getModule(CoreModule.class);
		this.module = module;
		this.entityProvider = module.appState.entityProvider;
	}

	@Override
	public void messageReceived(MessageConnection source, Message message) {
		StateUpdateMessage castMessage = (StateUpdateMessage) message;
		EntityData data = entityProvider.getData(castMessage.entityId);
		if (data == null) {
			return;
		}
		StaticEntityData staticData = data.getStaticData(source);
		DynamicMemberData[] dynamicData = data.getMemberData(staticData);
		ConnectionInfo sourceInfo = coreModule.getConnectionInfo(source);

		Collection<StateUpdateListener> listeners = module.collectListeners(
				data, staticData, coreModule.getConnectionInfo(source));
		for (StateUpdateListener l : listeners) {
			l.beforeInboundUpdate(sourceInfo, castMessage, data, staticData);
		}
		for (int i = 0; i < castMessage.fieldIds.length; i++) {
			int id = castMessage.fieldIds[i];
			Object value = castMessage.fieldValues[i];
			if (dynamicData[id].getClass().equals(
					OutboundDynamicMemberStateData.class)) {
				OutboundStaticMemberStateData sd = staticData.getData(id,
						OutboundStaticMemberStateData.class);
			}
			InboundDynamicMemberStateData memberData = (InboundDynamicMemberStateData) dynamicData[id];
			InboundStaticMemberStateData staticMemberData = staticData.getData(
					id, InboundStaticMemberStateData.class);
			if (castMessage.localTime > memberData.lastReceivedTime) {
				staticMemberData.writeAccessor.writeValue(data.entity,
						staticMemberData.interpreter.extractData(value));
				memberData.lastReceivedTime = castMessage.localTime;
			}

			for (StateUpdateListener l : listeners) {
				l.afterInboundUpdate(sourceInfo, castMessage, data, staticData);
			}
		}
	}
}
